{
 "cells": [
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-05T07:14:42.978676Z",
     "start_time": "2025-05-05T07:14:39.788570Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import torch\n",
    "from sympy import false\n",
    "from torch import nn\n",
    "\n",
    "\n",
    "def corr2d(X, K):  #@save\n",
    "\t\"\"\"计算二维互相关运算\"\"\"\n",
    "\th, w = K.shape\n",
    "\tY = torch.zeros((X.shape[0] - h + 1, X.shape[1] - w + 1))\n",
    "\tfor i in range(Y.shape[0]):\n",
    "\t\tfor j in range(Y.shape[1]):\n",
    "\t\t\tY[i, j] = (X[i:i + h, j:j + w] * K).sum()\n",
    "\treturn Y"
   ],
   "id": "d2fc74e768889504",
   "outputs": [],
   "execution_count": 1
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-05T07:14:43.055290Z",
     "start_time": "2025-05-05T07:14:42.997107Z"
    }
   },
   "cell_type": "code",
   "source": [
    "X = torch.tensor([[0.0, 1.0, 2.0], [3.0, 4.0, 5.0], [6.0, 7.0, 8.0]])\n",
    "K = torch.tensor([[0.0, 1.0], [2.0, 3.0]])\n",
    "corr2d(X, K)"
   ],
   "id": "4abb8e560a06beaf",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[19., 25.],\n",
       "        [37., 43.]])"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 2
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-05T07:14:43.225797Z",
     "start_time": "2025-05-05T07:14:43.210109Z"
    }
   },
   "cell_type": "code",
   "source": [
    "class Conv2D(nn.Module):\n",
    "\tdef __init__(self, kernel_size):\n",
    "\t\tsuper().__init__()\n",
    "\t\tself.weight = nn.Parameter(torch.rand(kernel_size))\n",
    "\t\tself.bias = nn.Parameter(torch.zeros(1))\n",
    "\n",
    "\tdef forward(self, x):\n",
    "\t\treturn corr2d(x, self.weight) + self.bias"
   ],
   "id": "4ccc3801be607011",
   "outputs": [],
   "execution_count": 3
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-05T07:14:43.718708Z",
     "start_time": "2025-05-05T07:14:43.704580Z"
    }
   },
   "cell_type": "code",
   "source": [
    "X = torch.ones((6, 8))\n",
    "X[:, 2:6] = 0\n",
    "X"
   ],
   "id": "bedea364733e1a69",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[1., 1., 0., 0., 0., 0., 1., 1.],\n",
       "        [1., 1., 0., 0., 0., 0., 1., 1.],\n",
       "        [1., 1., 0., 0., 0., 0., 1., 1.],\n",
       "        [1., 1., 0., 0., 0., 0., 1., 1.],\n",
       "        [1., 1., 0., 0., 0., 0., 1., 1.],\n",
       "        [1., 1., 0., 0., 0., 0., 1., 1.]])"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 4
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-05T07:14:44.030254Z",
     "start_time": "2025-05-05T07:14:44.012521Z"
    }
   },
   "cell_type": "code",
   "source": "K = torch.tensor([[1.0, -1.0]])",
   "id": "21627cb3fc9444fc",
   "outputs": [],
   "execution_count": 5
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-05T07:14:44.213751Z",
     "start_time": "2025-05-05T07:14:44.196079Z"
    }
   },
   "cell_type": "code",
   "source": "Y = corr2d(X, K)",
   "id": "3001dadd097a19b1",
   "outputs": [],
   "execution_count": 6
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-05T07:14:44.245598Z",
     "start_time": "2025-05-05T07:14:44.233547Z"
    }
   },
   "cell_type": "code",
   "source": "corr2d(X.t(), K)",
   "id": "30466bf4391d9560",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[0., 0., 0., 0., 0.],\n",
       "        [0., 0., 0., 0., 0.],\n",
       "        [0., 0., 0., 0., 0.],\n",
       "        [0., 0., 0., 0., 0.],\n",
       "        [0., 0., 0., 0., 0.],\n",
       "        [0., 0., 0., 0., 0.],\n",
       "        [0., 0., 0., 0., 0.],\n",
       "        [0., 0., 0., 0., 0.]])"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 7
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-05T07:14:44.401421Z",
     "start_time": "2025-05-05T07:14:44.323902Z"
    }
   },
   "cell_type": "code",
   "source": [
    "conv2d = nn.Conv2d(1, 1, kernel_size=(1, 2), bias=False)\n",
    "\n",
    "X = X.reshape((1, 1, 6, 8))\n",
    "Y = Y.reshape((1, 1, 6, 7))\n",
    "for i in range(10):\n",
    "\tY_hat = conv2d(X)\n",
    "\tl = (Y_hat - Y)**2\n",
    "\tconv2d.zero_grad()\n",
    "\tl.sum().backward()\n",
    "\tconv2d.weight.data[:] -= 3e-2 *conv2d.weight.grad\n",
    "\tif (i+1)%2==0:\n",
    "\t\tprint(f'epoch {i+1}, loss {l.sum():.3f}')"
   ],
   "id": "6f4c1bf52c23eb8a",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch 2, loss 8.663\n",
      "epoch 4, loss 1.474\n",
      "epoch 6, loss 0.256\n",
      "epoch 8, loss 0.046\n",
      "epoch 10, loss 0.009\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\admin\\anaconda3\\envs\\study\\lib\\site-packages\\torch\\_tensor.py:1128: UserWarning: Converting a tensor with requires_grad=True to a scalar may lead to unexpected behavior.\n",
      "Consider using tensor.detach() first. (Triggered internally at C:\\actions-runner\\_work\\pytorch\\pytorch\\pytorch\\aten\\src\\ATen\\native\\Scalar.cpp:23.)\n",
      "  return self.item().__format__(format_spec)\n"
     ]
    }
   ],
   "execution_count": 8
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-05T07:14:44.478344Z",
     "start_time": "2025-05-05T07:14:44.464484Z"
    }
   },
   "cell_type": "code",
   "source": "conv2d.weight.data.reshape((1, 2))",
   "id": "1b6bf4b8e2bd3b60",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[ 0.9797, -0.9898]])"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 9
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
